package bll

import (
	"jgt-oper/src/model"
	"jgt-oper/src/schema"
	"jgt-oper/src/util"
	"jgt-sdk/asapi"
	"sync"
	"time"

	"github.com/json-iterator/go"
	"github.com/pkg/errors"
	"github.com/spf13/viper"
)

// User 用户管理
type User struct {
	UserModel     model.IUser        `inject:"IUser"`
	AuthUserModel model.IAuthUser    `inject:"IAuthUser"`
	AuthCodeBll   *AuthCode          `inject:""`
	EnterpriseBll *Enterprise        `inject:""`
	FVBll         *FrequentlyVisitor `inject:""`
	sync.RWMutex
}

// QueryPage 查询分页数据
func (a *User) QueryPage(params schema.UserQueryParam, pageIndex, pageSize uint) (int64, []*schema.UserShow, error) {

	var (
		n      int64
		data   []*schema.User
		tel    string
		err    error
		result []*schema.UserShow
		auths  []*schema.AuthUser
		user   *schema.User
	)

	//电话精确查询
	if tel = params.Tel; tel != "" {
		n, auths, err = a.AuthUserModel.QueryPageByTel(tel, pageIndex, pageSize)
		if err != nil {
			return 0, nil, err
		}
		for _, v := range auths {
			user, err = a.UserModel.Get(v.ID)
			if err != nil {
				return 0, nil, err
			}
			if user != nil {
				show := a.getUserShow(user)
				result = append(result, show)
			}
		}

		return n, result, err
	}

	n, data, err = a.UserModel.QueryPage(params, pageIndex, pageSize)
	for _, v := range data {
		show := a.getUserShow(v)
		result = append(result, show)
	}

	return n, result, err
}

// Search 查询分页数据
func (a *User) Search(search string, count int) ([]*schema.UserShow, error) {

	var (
		auth   []*schema.AuthUser
		user   []*schema.User
		data   []*schema.User
		err    error
		result []*schema.UserShow
	)
	auth, err = a.AuthUserModel.Search(search, count)
	if err != nil {
		return nil, err
	}
	user, err = a.UserModel.Search(search, count)
	if err != nil {
		return nil, err
	}

	for _, v := range auth {
		u, _ := a.UserModel.Get(v.ID)
		if u != nil {
			data = append(data, u)
		}
	}

	for _, v := range user {
		if len(data) >= count {
			break
		}
		b := false
		for _, d := range data {
			if d.RecordID == v.RecordID {
				b = true
				break
			}
		}
		if b {
			continue
		}
		if v != nil {
			data = append(data, v)
		}
	}

	for _, v := range data {
		show := a.getUserShow(v)
		result = append(result, show)
	}

	return result, err
}

// getUserShow 拼装展示信息
func (a *User) getUserShow(item *schema.User) *schema.UserShow {
	if item == nil {
		return nil
	}
	show := new(schema.UserShow)
	show.ID = item.ID
	show.RecordID = item.RecordID
	show.Nickname = item.Nickname
	show.RealName = item.RealName
	show.Birthday = "个人机密"
	show.Photo = item.Photo
	show.Sign = "这个人很懒,没有签名"

	show.BanMsg = item.BanMsg
	show.BanComment = item.BanComment
	show.BanLogin = item.BanLogin
	show.BanEssay = item.BanEssay

	//查询电话,状态
	u, _ := a.AuthUserModel.Get(item.RecordID)
	if u != nil {
		show.Tel = u.Tel
	}
	if item.Deleted == 0 {
		show.Status = 1
	} else {
		show.Status = 2
	}
	show.Gender = item.Gender
	show.EnterpriseID = item.EnterpriseID
	//查询企业名称
	en, _ := a.EnterpriseBll.Get(item.EnterpriseID)
	if en != nil {
		show.EnterpriseName = en.Name
	}

	show.Post = item.Post
	show.UserType = item.UserType
	show.AuthStatus = item.AuthStatus

	show.Created = item.Created
	return show
}

// Create 创建用户
func (a *User) Create(item *schema.User) error {
	if item.AuthStatus == 0 {
		item.AuthStatus = 2
	}
	item.Created = time.Now().Unix()
	item.Deleted = 0
	item.Operator = ""
	return a.UserModel.Create(item)
}

// UpdateRegisterInfo 更新用户注册信息
func (a *User) UpdateRegisterInfo(recordID string, info *schema.UpdateUserRegisterInfo) error {
	item := util.StructToMap(info)
	if info.Photo == "" {
		delete(item, "photo")
	}

	if info.Nickname == "" {
		delete(item, "nickname")
	}

	if info.Gender == 0 {
		delete(item, "gender")
	}

	if len(item) == 0 {
		return nil
	}
	return a.UserModel.Update(recordID, item)
}

// Get 获取用户信息
func (a *User) Get(recordID string) (*schema.User, error) {
	return a.UserModel.Get(recordID)
}

// GetAuthUser 获取用户认证信息
func (a *User) GetAuthUser(recorID string) (*schema.AuthUser, error) {
	return a.AuthUserModel.Get(recorID)
}

// CheckNickname 检查用户昵称
func (a *User) CheckNickname(userID, nickname string) (bool, error) {
	if userID != "" {
		info, err := a.UserModel.Get(userID)
		if err != nil {
			return false, err
		} else if info == nil {
			return false, errors.New("无效的用户")
		} else if info.Nickname == nickname {
			return false, nil
		}
	}
	return a.UserModel.CheckNickname(nickname)
}

// QueryCommonFunction 查询常用功能
func (a *User) QueryCommonFunction(userID string) ([]string, error) {
	return a.UserModel.QueryCommonFunction(userID)
}

// SaveCommonFunction 保存常用功能
func (a *User) SaveCommonFunction(userID string, items []string) error {
	return a.UserModel.SaveCommonFunction(userID, items)
}

// Auth 用户认证
func (a *User) Auth(item *schema.AuthHistory) error {
	a.Lock()
	defer a.Unlock()

	userID := item.UserID
	user, err := a.UserModel.Get(userID)
	if err != nil {
		return err
	} else if user == nil {
		return errors.New("无效的用户")
	} else if user.AuthStatus == 1 {
		return errors.New("用户已认证")
	}

	authItem, err := a.AuthCodeBll.Get(item.CodeID)
	if err != nil {
		return err
	} else if authItem == nil {
		return errors.New("无效的认证码")
	} else if v := a.AuthCodeBll.Verify(authItem); !v {
		return errors.New("无效的认证码")
	}

	if authItem.EffectiveMode == 2 {
		err = a.AuthCodeBll.IncUsedNumber(authItem.RecordID)
		if err != nil {
			return err
		}
	}

	// 增加用户认证历史
	err = a.AuthCodeBll.CreateHistory(item)
	if err != nil {
		return err
	}

	// 更新用户信息
	info := map[string]interface{}{
		"real_name":     item.RealName,
		"enterprise_id": authItem.EnterpriseID,
		"user_type":     a.getUserType(authItem.CodeType, authItem.EnterpriseID),
		"post":          item.Post,
		"auth_status":   1,
	}
	err = a.UserModel.Update(userID, info)
	if err != nil {
		return err
	}

	return nil
}

// getUserType 查询用户类型
func (a *User) getUserType(codeType, enterpriseID string) string {
	eitem, err := a.EnterpriseBll.Get(enterpriseID)
	if err == nil && eitem != nil {
		switch {
		case codeType == "30" && eitem.EnterpriseMark == "2":
			codeType = "31"
		case codeType == "30" && eitem.EnterpriseMark == "3":
			codeType = "32"
		case codeType == "40" && eitem.EnterpriseMark == "2":
			codeType = "41"
		case codeType == "40" && eitem.EnterpriseMark == "3":
			codeType = "42"
		}
	}

	return codeType
}

// CancelAuth 取消授权
func (a *User) CancelAuth(recordID string) error {
	info := map[string]interface{}{
		"real_name":     "",
		"enterprise_id": "",
		"user_type":     "20",
		"post":          "",
		"auth_status":   2,
	}
	//	更新用户认证信息
	err := a.UserModel.Update(recordID, info)
	if err != nil {
		return err
	}

	return nil
}

// WriteOff 用户注销
func (a *User) WriteOff(recordID string) error {
	user, err := a.UserModel.Get(recordID)
	if err != nil {
		return err
	} else if user == nil {
		return errors.New("用户不存在")
	} else if user.Deleted > 0 {
		return errors.New("该用户已被注销")
	} else if user.UserType == viper.GetString("system_admin_user_type") {
		return errors.New("管理员用户不能被注销")
	} else if user.UserType == "40" || user.UserType == "41" {
		//	检查是否为唯一有效管理员
		ps := new(schema.UserQueryParam)
		ps.EnterpriseID = user.EnterpriseID
		ps.UserType = user.UserType
		ps.Status = 1
		_, ads, err := a.QueryPage(*ps, 1, 2)
		if err != nil {
			return err
		} else if len(ads) == 1 {
			if ads[0].RecordID == user.RecordID {
				return errors.New("企业唯一管理员不能注销,请先添加另一位管理员")
			} else {
				return errors.New("企业管理员注销失败")
			}
		}
	}

	info := map[string]interface{}{
		"deleted": time.Now().Unix(),
	}

	if err := a.AuthUserModel.Update(recordID, info); err != nil {
		return err
	}

	if err := a.UserModel.Update(recordID, info); err != nil {
		return err
	}
	return nil
}

// Count 获取用户统计
func (a *User) Count() (*schema.UserCount, error) {

	var (
		params = schema.UserQueryParam{}
		count  = new(schema.UserCount)
		err    error
	)
	params.AuthStatus = 1
	count.Auth, err = a.UserModel.Count(params)
	if err != nil {
		return nil, err
	}
	params.AuthStatus = 2
	count.UnAuth, err = a.UserModel.Count(params)
	if err != nil {
		return nil, err
	}
	count.All = count.Auth + count.UnAuth
	return count, nil
}

// CreateLoginHistory 创建登录历史
func (a *User) CreateLoginHistory(item *schema.LoginHistory) error {
	item.Created = time.Now().Unix()
	return a.UserModel.CreateLoginHistory(item)
}

// SaveSetting 保存用户设置
func (a *User) SaveSetting(userID string, item *schema.UserSettingItem) error {
	return a.UserModel.SaveSetting(&schema.UserSetting{UserID: userID, Settings: item})
}

// GetSetting 获取用户设置
func (a *User) GetSetting(userID string) (*schema.UserSettingItem, error) {
	item, err := a.UserModel.GetSetting(userID)
	if err != nil {
		return nil, err
	} else if item == nil {
		return nil, nil
	}
	return item.Settings, nil
}

// UpdatePassword 更新密码
func (a *User) UpdatePassword(traceID, userID, oldPassword, newPassword string) error {
	err := asapi.GetAPIWithTraceID(traceID).UpdatePwd(userID, oldPassword, newPassword)
	if err != nil {
		msg := jsoniter.Get([]byte(err.Error()), "message")
		if msg != nil {
			return errors.Wrapf(err, msg.ToString())
		}
		return errors.Wrapf(err, "更新密码发生错误")
	}
	return nil
}
